package com.alameda.service.user;

import com.alameda.api.user.UserOrganizationService;
import com.alameda.api.user.UserService;
import com.alameda.exception.BusinessException;
import com.alameda.mapper.user.UserOrganizationMapper;
import com.alameda.result.ResultEnum;
import com.alameda.user.bo.UserOrganizationBO;
import com.alameda.user.dto.UserOrganizationDTO;
import com.alameda.user.pojo.UserOrganizationDO;
import com.alameda.user.vo.UserOrganizationVO;
import com.alameda.utils.ExcelUtils;
import com.alameda.utils.ObjectUtils;
import com.alameda.utils.PubUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户组织 业务逻辑层 具体实现
 *
 * @author Lv
 * @date 2024/04/27
 */
@Slf4j
@Service
public class UserOrganizationServiceImpl extends ServiceImpl<UserOrganizationMapper, UserOrganizationDO> implements UserOrganizationService {

    @Autowired
    private UserOrganizationMapper userOrganizationMapper;

    /**
     * 查询组织列表
     *
     * @param userOrganizationDTO 用户组织数据传递对象
     * @return
     */
    @Override
    public IPage<UserOrganizationVO> listOrganization(UserOrganizationDTO userOrganizationDTO) {
        IPage<UserOrganizationDO> iPage = new Page<>(userOrganizationDTO.getPageNum(), userOrganizationDTO.getPageSize());
        IPage<UserOrganizationVO> pageData = userOrganizationMapper.findByOrganizationNameAndParentId(iPage,
                userOrganizationDTO.getOrganizationName(),
                userOrganizationDTO.getParentId());
        dealPageData(pageData);
        return pageData;
    }

    /**
     * 处理返回数据
     *
     * @param pageData 分页数据
     */
    private void dealPageData(IPage<UserOrganizationVO> pageData) {
        List<UserOrganizationVO> pageDataRecords = pageData.getRecords();
        if (PubUtils.isNotNull(pageDataRecords)) {
            pageDataRecords.forEach(item -> {
                if (PubUtils.isEmpty(item.getParentOrganizationName())) {
                    item.setParentOrganizationName("--");
                }
            });
        }
    }

    /**
     * 导出excel
     *
     * @param userOrganizationDTO 用户组织数据传递对象
     */
    @Override
    public void export(UserOrganizationDTO userOrganizationDTO) {
        List<UserOrganizationBO> userOrganizationBOList = getExportData(userOrganizationDTO);
        ExcelUtils.export(userOrganizationBOList, UserOrganizationBO.class, "组织部门");
    }

    /**
     * 最高权限组织id
     */
    private static final Long ADMIN_ORGANIZATION_ID = 1L;

    /**
     * 删除组织信息
     *
     * @param idList 组织id集合
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteByIds(List<Long> idList) {
        // 过滤掉最高组织id
        idList = idList.stream()
                .filter(item -> !ADMIN_ORGANIZATION_ID.equals(item))
                .collect(Collectors.toList());

        // 处理父组织和子组织同时删除场景
        dealDelete(idList);
        // 删除组织下的用户
        return removeUserByOrganizationIdList(idList);
    }

    /**
     * 新增或修改组织
     *
     * @param userOrganizationDTO 用户组织数据传递对象
     * @return
     */
    @Override
    public Boolean saveOrUpdateOrganization(UserOrganizationDTO userOrganizationDTO) {
        UserOrganizationDO userOrganizationDO = ObjectUtils.convert(userOrganizationDTO, UserOrganizationDO.class);
        return PubUtils.isNull(userOrganizationDO.getId()) ? dealOrganizationSave(userOrganizationDO) : dealOrganizationUpdate(userOrganizationDO);
    }

    /**
     * 处理修改
     *
     * @param userOrganizationDO 组织信息
     * @return
     */
    private Boolean dealOrganizationUpdate(UserOrganizationDO userOrganizationDO) {
        String organizationName = userOrganizationDO.getOrganizationName();
        UserOrganizationDO userOrganizationDb = this.getById(userOrganizationDO.getId());

        if (!userOrganizationDb.getOrganizationName().equals(organizationName)) {
            checkOrganizationName(userOrganizationDO);
        }
        return this.updateById(userOrganizationDO);
    }

    /**
     * 校验组织名称
     *
     * @param userOrganizationDO 组织信息
     * @return
     */
    private void checkOrganizationName(UserOrganizationDO userOrganizationDO) {
        String organizationName = userOrganizationDO.getOrganizationName();
        Long count = this.count(UserOrganizationDO.builder().organizationName(organizationName).build());
        if (count > 0) {
            BusinessException.throwException("已存在同名组织");
        }
    }

    /**
     * 处理新增
     *
     * @param userOrganizationDO 组织信息
     * @return
     */
    private Boolean dealOrganizationSave(UserOrganizationDO userOrganizationDO) {
        checkOrganizationName(userOrganizationDO);
        return this.save(userOrganizationDO);
    }

    @Autowired
    private UserService userService;

    /**
     * 删除组织下的用户
     *
     * @param organizationIdList 组织id集合
     * @return
     */
    private Boolean removeUserByOrganizationIdList(List<Long> organizationIdList) {
        return userService.removeByOrganizationIdList(organizationIdList);
    }

    /**
     * 处理父组织和子组织同时删除场景
     *
     * @return
     */
    private Boolean dealDelete(List<Long> idList) {
        List<UserOrganizationDO> userOrganizationDOList = this.listByIds(idList);

        // 过滤出删除数据中包含的父级组织id集合
        Set<Long> parentIdList = userOrganizationDOList.stream()
                .map(UserOrganizationDO::getParentId)
                .filter(PubUtils::isNotNull)
                .collect(Collectors.toSet());

        if (PubUtils.isNotEmpty(parentIdList)) {
            return deleteContainsParentId(parentIdList, idList);
        } else {
            return deleteUnContainsParentId(idList);
        }
    }

    /**
     * 处理不包含父级组织id删除的场景
     *
     * @param idList 删除数据id集合
     * @return
     */
    private Boolean deleteUnContainsParentId(List<Long> idList) {
        List<UserOrganizationDO> organizationDOList = userOrganizationMapper.findByIdInOrParentIdIn(idList, idList);
        if (PubUtils.isNotNull(organizationDOList) && (organizationDOList.size() == idList.size())) {
            return this.removeByIds(idList);
        } else {
            throwDeleteException();
        }
        return Boolean.FALSE;
    }

    /**
     * 抛出删除异常
     */
    private void throwDeleteException() {
        log.error("删除父组织必须同时删除所有子组织");
        BusinessException.throwException(ResultEnum.FAILED, "删除父组织必须同时删除所有子组织");
    }

    /**
     * 处理包含父级组织id删除的场景
     *
     * @param parentIdList 父级组织id集合
     * @param idList       删除数据id集合
     * @return
     */
    private Boolean deleteContainsParentId(Set<Long> parentIdList, List<Long> idList) {
        return this.removeByIds(idList);
    }

    /**
     * 获取导出数据
     *
     * @param userOrganizationDTO 用户组织数据传递对象
     * @return
     */
    private List<UserOrganizationBO> getExportData(UserOrganizationDTO userOrganizationDTO) {
        IPage<UserOrganizationVO> pageData = listOrganization(userOrganizationDTO);
        if (PubUtils.isEmpty(userOrganizationDTO.getIdList())) {
            return ObjectUtils.convertList(pageData.getRecords(), UserOrganizationBO.class);
        } else {
            List<UserOrganizationVO> userOrganizationVOList = pageData.getRecords().stream()
                    .filter(item -> userOrganizationDTO.getIdList().contains(item.getId()))
                    .collect(Collectors.toList());

            return ObjectUtils.convertList(userOrganizationVOList, UserOrganizationBO.class);
        }
    }
}
